#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <libgen.h>
#include <locale.h>

#include "common.h"
#include "extractor.h"

// #define DEBUG
#include "log.h"

#if defined(EX_GUI)
#include "extractor-gui.h"
#endif

static i32   ex_run_cli(const char *source, const char*dest, const AROptions *options);
static char *ex_path_stem(const char *path);
static void  ex_print_usage(const char *progname);

#if defined(EX_GUI)
static i32   ex_run_gui(const char *source, const char *destdir, const AROptions *options);
#endif

static DirMode parse_dir_mode(const char *mode)
{
    xprintf(LOG_LEVEL_TRACE, "parse_dir_mode() mode = %s", mode);

    if (strcmp("auto", mode) == 0) {
	return DIR_MODE_AUTO;
    }
    if (strcmp("always", mode) == 0) {
	return DIR_MODE_ALWAYS;
    }
    if (strcmp("never", mode) == 0) {
	return DIR_MODE_NEVER;
    }

    die("Unknown dirmode '%s', expected one of 'auto', 'always', or 'never'.", mode);
}

int main(int argc, char *argv[])
{
    AROptions options;
    char *destdir;
    char *source;
    i32 status;
    i32 i;

#if defined(EX_GUI)
    bool use_gui = false;
#endif

    options.mode = DIR_MODE_AUTO;
    options.verbose = false;
    source = NULL;

    setlocale(LC_ALL, "");

    if (argc < 2) {
        ex_print_usage(argv[0]);
        return EXIT_FAILURE;
    }

    for (i = 1; i < argc; ++i) {
        if (strcmp(argv[i], "-help") == 0) {
            ex_print_usage(argv[0]);
            return EXIT_SUCCESS;
        }

	if (strcmp(argv[i], "-verbose") == 0)
	{
	    options.verbose = true;
	    continue;
	}

        if (strncmp(argv[i], "-dirmode:", 9) == 0) {
            options.mode = parse_dir_mode(strchr(argv[i], ':') + 1);
            continue;
        }

#if defined(EX_GUI)
        if (strcmp(argv[i], "-gui") == 0) {
            use_gui = true;
            continue;
        }
#else
        if (strcmp(argv[i], "-gui") == 0) {
            xprintf(LOG_LEVEL_WARNING, "ex was not compiled to support GUI");
            continue;
        }
#endif
        source = argv[i];
    }

    if (NULL == source) {
        ex_print_usage(argv[0]);
        return EXIT_FAILURE;
    }

    destdir = ex_path_stem(basename(source));

#if defined(EX_GUI)
    if (use_gui) {
        status = ex_run_gui(source, destdir, &options);
    } else {
        status = ex_run_cli(source, destdir, &options);
    }
#else
    status = ex_run_cli(source, destdir, &options);
#endif

    free(destdir);

    return status;
}

static i32 ex_run_cli(const char *source, const char *destdir, const AROptions *options)
{
    if (!extractor_init(source, destdir, options)) {
        return EXIT_FAILURE;
    }
    extractor_run();
    extractor_deinit();
    return EXIT_SUCCESS;
}

#if defined(EX_GUI)
static i32 ex_run_gui(const char *source, const char *destdir, const AROptions* options)
{
    if (!extractor_gui_init(source, destdir, options)) {
        return EXIT_FAILURE;
    }
    extractor_gui_run();
    extractor_gui_deinit();
    return EXIT_SUCCESS;
}
#endif

static char *ex_path_stem(const char *path)
{
    char *stem;
    size_t len = strlen(path);

    while (len > 0 && path[len] != '.') {
        --len;
    }

    if (len <= 0) {
        return NULL;
    }

    stem = (char*)malloc(len + 1);
    memset(stem, 0, len + 1);
    memcpy(stem, path, len);
    return stem;
}

static void ex_print_usage(const char *progname)
{
#if defined(EX_GUI)
    printf("usage: %s [-gui] [-verbose] [-dirmode:<mode>] FILE\n", progname);
#else
    printf("usage: %s [-verbose] [-dirmode:<mode>] FILE\n", progname);
#endif
    puts("\n-dirmode controls how ex creates directories from archives. There are three possible values:\n"
	 "\n"
	 "  - \"auto\" means a directory will be created if the archive does not contain a top-level directory.\n"
	 "  - \"always\" means a directory will always be created, even if there is already a top-level directory.\n"
	 "  - \"never\" means no directory will be created. If there is a top-level directory, that will still exist.\n"
         "\nex will use \"auto\" by default."
	);
}
